using Network.Delegate;
using Network.Tcp.Pooling;
using Network.Tcp.TcpConfig;
using Network.UtilityHelper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;

namespace Network.Tcp.NetSession
{
    public abstract class Session
    {
        protected readonly NotifyEventHandler<CompleteNotify, Session> _notifyEventHandler;
        protected readonly ConfigBase _configuration;
        protected readonly AwaiterPool _awaiterPool;
        protected readonly SessionPool _sessionPool;
        protected readonly LogHelper _logger;

        protected readonly NetEngineBased _agent;
        protected readonly object _opsLock = new object();
        protected ConnectionState _state;
        protected byte[] _completebuffer;
        protected Socket _socket;
        protected DateTime _startTime;

        public int SendTransferredBytes { get; protected set; }
        public int ReceiveBytesTransferred { get; protected set; }
        public byte[] CompletedBuffer { get { return _completebuffer; } }
        public object[] AppTokens { get; set; }
        public Socket Socket { get { return _socket; } }
        public bool Connected { get { return _socket != null && _socket.Connected; } }
        public ConnectionState State { get { return _state; } internal set { _state = value; } }
        public DateTime StartTime { get { return _startTime; } }



        internal Session(
            NotifyEventHandler<CompleteNotify, Session> notifyEventHandler,
            ConfigBase configuration,
            AwaiterPool handlerSaeaPool,
            SessionPool sessionPool,
            NetEngineBased agent,
            LogHelper logHelper)
        {
            _notifyEventHandler = notifyEventHandler;
            _configuration = configuration;
            _awaiterPool = handlerSaeaPool;
            _sessionPool = sessionPool;
            _agent = agent;
            _logger = logHelper;
        }

        internal abstract void Attach(Socket socket);

        internal abstract void Detach();

        internal abstract void StartProcess();

        public abstract void SendAsync(byte[] data);

        public abstract void SendAsync(byte[] data, int offset, int lenght);

        public abstract void Close(bool notify);
    }
}
